package br.uvv.sao.managedBean;

import java.io.Serializable;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;

import sun.misc.BASE64Encoder;
import br.uvv.sao.domain.Aluno;
import br.uvv.sao.domain.Perfil;
import br.uvv.sao.domain.Professor;
import br.uvv.sao.domain.Usuario;
import br.uvv.sao.enums.SituUsuario;
import br.uvv.sao.rn.AlunoRN;
import br.uvv.sao.util.MsgUtil;
import br.uvv.sao.util.Util;
public class AlunoBean implements Serializable{
	private static final long serialVersionUID = 1L;
	
	private Long id;
	private Aluno alunoInstance;
	private Aluno alunoInstanceTemp;
	private Professor professorInstance;
	private List<Aluno> alunoList;
	private List<Perfil> perfilList; 
	private AlunoRN alunoRN;
	private Perfil perfilTemp;
	private String senhaConfirm;
	private String variavelBusca;
	private String senhaAtual;
	private String senhaNova;
	private String senhaNovaConfirm;
	
	public String goHome(){
		inicializarVariaveis();
		return "goHome";
	}
	
	public String goShow(){
		inicializarVariaveis();
		return "goAlunos";
	}
	
	public String goCreate(){
		id = null;
		alunoInstanceTemp = new Aluno();
		alunoList = new ArrayList<Aluno>();
		variavelBusca = "";
		senhaConfirm = "";
		alunoInstance = new Aluno();
		alunoInstance.setMatricula(alunoRN.gerarCodigo());
		return "goCreate";
	}
	
	public String goEdit(){
		id = null;
		alunoInstanceTemp = new Aluno();
		alunoList = new ArrayList<Aluno>();
		variavelBusca = "";
		senhaConfirm = "";
		if(alunoInstance.getSituacao().equals(SituUsuario.Ativo)){
			return "goEdit";
		}else{
			MsgUtil.msgError("AVISO: Não é permitido editar um aluno desativado.");
		}
		return null;
	}
	
	public void filtrarAluno(){
		alunoList = alunoRN.filtrar(variavelBusca);
	}
	
	public void selecionarAluno(){
		if(alunoInstanceTemp.getId() != null){
			alunoInstance = alunoRN.carregar(alunoInstanceTemp.getId());
		}
		alunoInstanceTemp = new Aluno();
		variavelBusca = "";
		senhaAtual = "";
		senhaNova = "";
		senhaNovaConfirm = "";
		alunoList = new ArrayList<Aluno>();
	}
	
	public String salvar(){
		if(alunoInstance.getSenha().equals(senhaConfirm)){
			if(alunoRN.salvar(alunoInstance)){
				return "goShow";
			}else{
				return null;
			}
		}else{
			MsgUtil.msgError("ERRO: As senhas devem ser iguais.");
	        return null;
		}
	}
	
	public String atualizar(){
		alunoRN.salvar(alunoInstance);
		return "goShow";
	}
	
	public String atualizarMinhaPagina(){
		alunoRN.salvar(alunoInstance);
		return "goMinhaPagina";
	}
	
	public String alterarSenha(){
		alunoRN.alterarSenha(alunoInstance, senhaAtual, senhaNova, senhaNovaConfirm);
		senhaAtual = "";
		senhaNova = "";
		senhaNovaConfirm = "";
		return null;
	}
	
	public void desativar(){
		if(!alunoInstance.getSituacao().equals(SituUsuario.Ativo)){
			MsgUtil.msgWarn("AVISO: Este aluno já está desativado.");
		}else{
			alunoInstance.setSituacao(SituUsuario.Desativado);
			alunoRN.salvar(alunoInstance);
		}
	}
	
	public String desistirCreate(){
		inicializarVariaveis();
		return "goShow";
	}
	
	public String desistirUpdate(){
		id = null;
		alunoInstanceTemp = new Aluno();
		alunoList = new ArrayList<Aluno>();
		variavelBusca = "";
		senhaConfirm = "";
		alunoInstance = alunoRN.carregar(alunoInstance.getId());
		return "goShow";
	}
	
	public String desistirMinhaPaginaEdit(){
		id = null;
		alunoInstanceTemp = new Aluno();
		alunoList = new ArrayList<Aluno>();
		variavelBusca = "";
		senhaConfirm = "";
		alunoInstance = alunoRN.carregar(alunoInstance.getId());
		return "goMinhaPagina";
	}
	
	public String paginaAluno(){
		Usuario usuario = Util.getUsuarioLogado();
		if(usuario instanceof Aluno){
			alunoInstance = (Aluno) usuario;
		}else{
			alunoInstance = new Aluno();
			MsgUtil.msgWarn("É preciso estar logado com um aluno para acessar esta funcionalidade.");
			return "goHome";
		}
		return "goPaginaAluno";
	}
	
	public void mudarStatus(){
		alunoRN.salvar(alunoInstance);
	}
	
	@PostConstruct
	public void init(){
		alunoRN = new AlunoRN();
		inicializarVariaveis();
	}
	
	public void inicializarVariaveis(){
		id = null;
		alunoInstance = new Aluno();
		alunoInstanceTemp = new Aluno();
		professorInstance = new Professor();
		alunoList = new ArrayList<Aluno>();
		variavelBusca = "";
		senhaConfirm = "";
		senhaAtual = "";
		senhaNova = "";
		senhaNovaConfirm = "";
		perfilTemp = new Perfil();
		perfilList = alunoRN.listarPerfis();
	}
	
	public void validateEmail(FacesContext context, UIComponent toValidate, Object value) {  
	    String email = (String) value;
	    Pattern p = Pattern.compile("^[\\w-]+(\\.[\\w-]+)*@([\\w-]+\\.)+[a-zA-Z]{2,7}$");  
	    Matcher m = p.matcher(email);
	    if (!m.find()) {
	    	((UIInput)toValidate).setValid(false);
	    	FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "O campo 'Email' não contém um email válido!", "");
	    	context.addMessage(toValidate.getClientId(context), message); 
	    	return;
	    }
	    
	    Boolean temElementos = alunoRN.verificarEmail(email,alunoInstance);
	    
	    if (temElementos){
	        ((UIInput)toValidate).setValid(false);
	        FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Já existe um aluno com este EMAIL na base de dados!", "");  
	        context.addMessage(toValidate.getClientId(context), message);  
	    }  
	}
	
	public void validateNomeCompleto(FacesContext context, UIComponent toValidate, Object value) {  
		String nome = (String) value;
	    
		Boolean temElementos = alunoRN.verificarNome(nome,alunoInstance);
	    
	    if (temElementos){
	        ((UIInput)toValidate).setValid(false);
	        FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Já existe um aluno com este NOME na base de dados!", "");  
	        context.addMessage(toValidate.getClientId(context), message);  
	    }  
	}
	
	public Aluno getAlunoInstance() {
		return alunoInstance;
	}
	public List<Aluno> getAlunoList() {
		return alunoList;
	}
	public void setAlunoInstance(Aluno alunoInstance) {
		this.alunoInstance = alunoInstance;
	}
	public void setAlunoList(List<Aluno> alunoList) {
		this.alunoList = alunoList;
	}
	public Long getId() {
		return id;
	}
	public void setId(Long id) {
		this.id = id;
	}
	public Aluno getAlunoInstanceTemp() {
		return alunoInstanceTemp;
	}
	public void setAlunoInstanceTemp(Aluno alunoInstanceTemp) {
		this.alunoInstanceTemp = alunoInstanceTemp;
	}
	public Professor getProfessorInstance() {
		return professorInstance;
	}
	public void setProfessorInstance(Professor professorInstance) {
		this.professorInstance = professorInstance;
	}
	public AlunoRN getAlunoRN() {
		return alunoRN;
	}
	public void setAlunoRN(AlunoRN alunoRN) {
		this.alunoRN = alunoRN;
	}
	public String getVariavelBusca() {
		return variavelBusca;
	}
	public void setVariavelBusca(String variavelBusca) {
		this.variavelBusca = variavelBusca;
	}
	public String getSenhaConfirm() {
		return senhaConfirm;
	}
	public void setSenhaConfirm(String senhaConfirm) {
		this.senhaConfirm = codificar(senhaConfirm);
	}
	public String getSenhaAtual() {
		return senhaAtual;
	}
	public void setSenhaAtual(String senhaAtual) {
		this.senhaAtual = codificar(senhaAtual);
	}
	public String getSenhaNova() {
		return senhaNova;
	}
	public void setSenhaNova(String senhaNova) {
		this.senhaNova = senhaNova;
	}
	public String getSenhaNovaConfirm() {
		return senhaNovaConfirm;
	}
	public void setSenhaNovaConfirm(String senhaNovaConfirm) {
		this.senhaNovaConfirm = senhaNovaConfirm;
	}
	private String codificar(String senha){
		try {
			MessageDigest digest = MessageDigest.getInstance("SHA1");
			digest.update(senha.getBytes());
			BASE64Encoder encoder = new BASE64Encoder ();
			senha =  encoder.encode (digest.digest ()); 
		} catch (NoSuchAlgorithmException e) {
			System.out.println("ERRO: Erro ao codificar senha.");
			e.printStackTrace();
		}
		return senha;
	}

	public Perfil getPerfilTemp() {
		return perfilTemp;
	}

	public void setPerfilTemp(Perfil perfilTemp) {
		this.perfilTemp = perfilTemp;
	}

	public List<Perfil> getPerfilList() {
		return perfilList;
	}

	public void setPerfilList(List<Perfil> perfilList) {
		this.perfilList = perfilList;
	}
}
